package com.chinapost.service.impl;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.chinapost.dao.BaseDaoI;
import com.chinapost.po.Tdept;
import com.chinapost.po.Tresource;
import com.chinapost.po.Trole;
import com.chinapost.po.Tuser;
import com.chinapost.service.UserServiceI;
import com.chinapost.util.Encrypt;
import com.chinapost.vo.DataGrid;
import com.chinapost.vo.User;

@Service("userService")
public class UserServiceImpl implements UserServiceI {

	private BaseDaoI<Tuser> userDao;
	private BaseDaoI<Tdept> deptDao;
	private BaseDaoI<Trole> roleDao;

	public BaseDaoI<Tdept> getDeptDao() {
		return deptDao;
	}

	@Autowired
	public void setDeptDao(BaseDaoI<Tdept> deptDao) {
		this.deptDao = deptDao;
	}

	public BaseDaoI<Trole> getRoleDao() {
		return roleDao;
	}

	@Autowired
	public void setRoleDao(BaseDaoI<Trole> roleDao) {
		this.roleDao = roleDao;
	}

	public BaseDaoI<Tuser> getUserDao() {
		return userDao;
	}

	@Autowired
	public void setUserDao(BaseDaoI<Tuser> userDao) {
		this.userDao = userDao;
	}

	@Override
	public void add(User user) {
		Tuser t = new Tuser();
		Date d = new Date();
		BeanUtils.copyProperties(user, t);
		t.setCid(UUID.randomUUID().toString());
		t.setCpwd(Encrypt.e(user.getCpwd().trim()));
		t.setCcreatedate(new Timestamp(d.getTime()));
		t.setCmodifydate(new Timestamp(d.getTime()));
		t.setTdept(deptDao.get(Tdept.class, user.getDeptid()));
		t.setCstate(1);
		t.setClogin(0);
		userDao.save(t);
		this.saveUserRole(user, t);
	}

	private void saveUserRole(User user, Tuser u) {
		if (user.getRoleIds() != null) {
			u.setTroles(new HashSet<Trole>());
			for (String id : user.getRoleIds().split(",")) {
				if (!StringUtils.isBlank(id)) {
					Trole trole = roleDao.get(Trole.class, id.trim());
					if (trole != null) {
						u.getTroles().add(trole);
					}
				}
			}
		}
	}

	@Override
	public void edit(User user) {
		Tuser t = userDao.get(Tuser.class, user.getCid());
		BeanUtils.copyProperties(user, t, new String[] { "ccreatedate", "cid", "cpwd", "clogin", "cstate","clastlogin" });
		Date d = new Date();
		t.setCmodifydate(new Timestamp(d.getTime()));
		if (user.getCpwd() != null && !user.getCpwd().isEmpty()) {
			t.setCpwd(Encrypt.e(user.getCpwd()));
		}
		t.setTdept(deptDao.get(Tdept.class, user.getDeptid()));
		this.saveUserRole(user, t);
	}

	@Override
	public void delete(User user) {
		String cids = "";
		if (user.getIds() != null) {
			String ids = user.getIds();
			for (String cid : ids.split(",")) {
				cids += "'" + cid + "'" + ",";
			}
			cids = cids.substring(0, cids.length() - 1);
			String hql = "delete Tuser t where t.cid in (" + cids + ")";
			userDao.executeHql(hql);
		}

	}

	@Override
	public User login(User user) {
		Map<String, Object> m = new HashMap<String, Object>();
		User u = new User();
		List<Tuser> tuserList = null;
		String hql = " from Tuser t where  t.cname= :name ";
		m.put("name", user.getCname());
		tuserList = userDao.find(hql, m);
		if (tuserList == null || tuserList.size() == 0) {
			u.setError(1);
			u.setSuccess(false);
			return u;
		}
		hql += " and t.cpwd = :password";
		m.put("password", Encrypt.e(user.getCpwd()));
		tuserList = userDao.find(hql, m);
		if (tuserList == null || tuserList.size() == 0) {
			u.setError(2);
			u.setSuccess(false);
			return u;
		}
		hql += " and t.cstate =1";
		Tuser t = userDao.get(hql, m);
		if (tuserList == null || tuserList.size() == 0) {
			u.setError(3);
			u.setSuccess(false);
			return u;
		} else {
			t.setClogin(t.getClogin()+1);
			t.setClastlogin(new Timestamp((new Date()).getTime()));
			BeanUtils.copyProperties(t, u, new String[] { "cpwd" });
			u.setDeptid(t.getTdept().getCid());
			u.setDeptname(t.getTdept().getCname());
			u.setSuccess(true);
			u = setRoleResource(t, u);
			return u;
		}
	}

	private User setRoleResource(Tuser t, User user) {
		// 获取用户所有角色
		String roleIds = "";
		String roleNames = "";
		String resourceUrls ="";
		Boolean b1 = false;
		Set<Trole> troles = t.getTroles();
		Set<Tresource> tresources = new HashSet<Tresource>();
		if (troles != null && troles.size() > 0) {
			for (Trole trole : troles) {
				if (b1) {
					roleIds += ",";
					roleNames += ",";
				}
				roleIds += trole.getCid();
				roleNames += trole.getCname();
				// 添加用户的所有可访问资源合集
				tresources.addAll(trole.getTresources());
				b1 = true;
			}
		}
		user.setRoleIds(roleIds);
		user.setRoleNames(roleNames);
		List<Tresource> list = new ArrayList<Tresource>(tresources);
		Boolean b2 = false;
		for (Tresource resource : list){
			if (b2){
				resourceUrls += ",";
			}
			resourceUrls += resource.getCurl();
			b2 = true;
		}
		user.setResourceUrls(resourceUrls);
		return user;
	}

	@Override
	public boolean changePwd(User user) {
		boolean b = false;
		if (user != null && user.getCid() != null && user.getCpwd() != null && user.getNewpwd() != null) {
			Tuser t = userDao.get(Tuser.class, user.getCid());
			if (t.getCpwd().equals(Encrypt.e(user.getCpwd()))) {
				t.setCpwd(Encrypt.e(user.getNewpwd()));
				Date d = new Date();
				t.setCmodifydate(new Timestamp(d.getTime()));
				b = true;
			}
		}
		return b;
	}

	@Override
	public DataGrid datagrid(User user) {
		DataGrid dg = new DataGrid();
		dg.setRows(listRows(find(user)));
		dg.setTotal(total(user));
		return dg;
	}

	private Long total(User user) {
		String hql = "select count(*) from Tuser t where 1=1";
		Map<String, Object> params = new HashMap<String, Object>();
		hql = addWhere(user, hql, params);
		return userDao.count(hql, params);
	}

	private List<Tuser> find(User user) {
		String hql = "from Tuser t where 1=1";
		Map<String, Object> params = new HashMap<String, Object>();
		hql = addWhere(user, hql, params);
		if (user.getOrder() != null && user.getSort() != null) {
			hql += " order by " + user.getSort() + " " + user.getOrder();
		}
		return userDao.find(hql, params, user.getPage(), user.getRows());
	}

	private List<User> listRows(List<Tuser> lt) {
		List<User> rows = new ArrayList<User>();
		if (lt != null && lt.size() > 0) {
			for (Tuser t : lt) {
				User sub = new User();
				BeanUtils.copyProperties(t, sub, new String[] { "cpwd" });
				sub.setDeptid(t.getTdept().getCid());
				sub.setDeptname(t.getTdept().getCname());
				Set<Trole> troles = t.getTroles();
				String roleIds = "";
				String roleNames = "";
				boolean b = false;
				if (troles != null && troles.size() > 0) {
					for (Trole trole : troles) {
						if (b) {
							roleIds += ",";
							roleNames += ",";
						}
						roleIds += trole.getCid();
						roleNames += trole.getCname();
						b = true;
					}
				}
				sub.setRoleIds(roleIds);
				sub.setRoleNames(roleNames);
				rows.add(sub);
			}
		}
		return rows;
	}

	private String addWhere(User user, String hql, Map<String, Object> params) {
		if (user != null && user.getCid() != null && !user.getCid().trim().equals("")) {
			hql += " and t.cid = :id ";
			params.put("id", user.getCid());
		}
		if (user != null && user.getDeptIds()!=null && user.getDeptIds().size()>0){
			hql += " and t.tdept.cid in (:deptids)";
			params.put("deptids", user.getDeptIds());
		}
		if (user != null && user.getCname() != null && !user.getCname().trim().equals("")) {
			hql += " and t.cname like :username ";
			params.put("username", "%%" + user.getCname() + "%%");
		}
		return hql;
	}

	@Override
	public void changeStatus(User user) {
		if (user != null && user.getCid() != null) {
			Tuser t = userDao.get(Tuser.class, user.getCid());
			if (t.getCstate() == 1) {
				t.setCstate(0);
			} else {
				t.setCstate(1);
			}
			Date d = new Date();
			t.setCmodifydate(new Timestamp(d.getTime()));
		}
	}

}
